// #include <pthread.h>
// #include <string>
// #include <vector>
// #include <iostream>
// #include <unistd.h>

// using namespace std;

// class customer
// {
// public:
//     int _ticket_num = 0;
//     pthread_t tid;
//     string _name;
// };

// pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

// int g_ticket = 10000;

// void *buyTicket(void *arg)
// {
//     customer *cust = (customer *)arg;
//     while (1)
//     {
//         pthread_mutex_lock(&mutex);
//         if (g_ticket > 0)
//         {
//             usleep(1000);
//             cout << cust->_name << " get ticket :" << g_ticket << endl;
//             g_ticket--;
//             cust->_ticket_num++;
//             pthread_mutex_unlock(&mutex);
//         }
//         else
//         {
//             pthread_mutex_unlock(&mutex);
//             break;
//         }
//     }
//     return nullptr;
// }

// int main()
// {
//     vector<customer> custs(5);
//     for (int i = 0; i < custs.size(); i++)
//     {
//         custs[i]._name = "customer-" + to_string(i+1);
//         pthread_create(&custs[i].tid, nullptr, buyTicket, &custs[i]);
//     }

//     for(int i=0;i<custs.size();i++)
//     {
//         pthread_join(custs[i].tid, nullptr);
//     }

//     for(int i=0;i<custs.size();i++)
//     {
//         cout<<custs[i]._name<<" get tickets : "<<custs[i]._ticket_num<<endl;
//     }
//     return 0;
// }

// class thread
// {
// public:
//     pthread_t _tid;
//     string _name;
// };

// pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
// pthread_cond_t g_cond = PTHREAD_COND_INITIALIZER;

// void master()
// {
//     while (1)
//     {
//         sleep(2);
//         cout << "------------------------" << endl;
//         pthread_cond_broadcast(&g_cond);
//     }
// }

// void *threadRun(void *arg)
// {
//     thread *t = (thread *)arg;
//     while (1)
//     {
//         pthread_mutex_lock(&g_mutex);
//         pthread_cond_wait(&g_cond, &g_mutex);
//         cout << t->_name << " wake up!" << endl;
//         pthread_mutex_unlock(&g_mutex);
//     }
//     return nullptr;
// }

// int main()
// {
//     vector<thread> threads(5);

//     for (int i = 0; i < threads.size(); i++)
//     {
//         threads[i]._name = "thread- " + to_string(i + 1);
//         pthread_create(&threads[i]._tid, nullptr, threadRun, (void *)&threads[i]);
//     }

//     master();

//     return 0;
// }

#include <vector>
#include <mutex>
#include <unistd.h>
#include <iostream>
// #include "LockGuard.hpp"
#include "Thread.hpp"

using namespace ThreadModule;

class ThreadData
{
public:
    ThreadData(int &tickets, std::string &name, std::mutex &mutex)
        : _tickets(tickets), _name(name), _mutex(mutex)
    {
    }

    ~ThreadData()
    {
    }

public:
    int &_tickets;
    std::string _name;
    int _total;
    std::mutex &_mutex;
};

int g_tickets = 10000;

const int num = 4;

void route(ThreadData *td)
{
    while (true)
    {
        // LockGuard guard(&td->_mutex);
        std::lock_guard<std::mutex> lock(td->_mutex);
        if (td->_tickets > 0)
        {
            usleep(1000);
            std::cout << td->_name << " is running, get tickets: " << td->_total << std::endl;
            td->_tickets--;
            td->_total++;
        }
        else
        {
            break;
        }
    }
}

int main()
{
    std::mutex mutex;
    // pthread_mutex_init(&mutex, nullptr);

    std::vector<Thread<ThreadData *>> threads;
    std::vector<ThreadData *> datas;

    for (int i = 0; i < num; i++)
    {
        std::string name = "thread - " + std::to_string(i + 1);
        ThreadData *td = new ThreadData(g_tickets, name, mutex);
        threads.emplace_back(route, td, name);
        datas.emplace_back(td);
    }

    for (auto &thread : threads)
    {
        thread.Start();
    }

    for (auto &thread : threads)
    {
        thread.Join();
    }

    sleep(1);
    for (auto &data : datas)
    {
        std::cout << data->_name << " : " << data->_total << std::endl;
        delete data;
    }

    return 0;
}
